package com.greatwqs.wmall.user.provider.service.impl;

import com.greatwqs.wmall.common.module.constants.RedisKey;
import com.greatwqs.wmall.common.module.exception.AppException;
import com.greatwqs.wmall.common.module.exception.ErrorCode;
import com.greatwqs.wmall.common.module.model.LoginUser;
import com.greatwqs.wmall.common.module.util.JsonUtil;
import com.greatwqs.wmall.user.provider.manager.UserLoginManager;
import com.greatwqs.wmall.user.provider.manager.UserManager;
import com.greatwqs.wmall.user.provider.model.dto.LoginDto;
import com.greatwqs.wmall.user.provider.model.po.User;
import com.greatwqs.wmall.user.provider.model.po.UserLogin;
import com.greatwqs.wmall.user.provider.model.vo.LoginVo;
import com.greatwqs.wmall.user.provider.service.UserLoginService;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;

/**
 * @author wang-qingsong
 */
@Slf4j
@Service
public class UserLoginServiceImpl implements UserLoginService {

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserLoginManager userLoginManager;

    @Autowired
    private UserManager userManager;

    @Override
    @Transactional
    public LoginVo login(LoginDto loginDto) {
        log.info("login loginDto: {}", JsonUtil.toJson(loginDto));
        User exist = userManager.getPoByLoginId(loginDto.getLoginId());
        if (exist == null) {
            log.warn("db user not found, loginDto: {}", JsonUtil.toJson(loginDto));
            throw new AppException(ErrorCode.USER_NOT_FOUND);
        }
        if (!StringUtils.equals(exist.getUserPwd(), loginDto.getPassword())) {
            log.warn("db user password not match, loginDto: {}", JsonUtil.toJson(loginDto));
            throw new AppException(ErrorCode.USER_LOGIN_PASSWORD_ERROR);
        }

        UserLogin userLogin = this.userLoginManager.createLogin(exist.getUserId());
        setLoginTokenCache(userLogin.getLoginToken(), exist);
        return LoginVo.of(exist.getUserId(), userLogin.getLoginToken());
    }

    private void setLoginTokenCache(String loginToken, User exist) {
        LoginUser loginUser = modelMapper.map(exist, LoginUser.class);
        stringRedisTemplate.opsForValue().set(RedisKey.loginToken(loginToken), JsonUtil.toJson(loginUser), Duration.ofHours(2));
    }
}
